package opgave1;

import java.io.PrintStream;
import java.util.Scanner;
import java.util.regex.Pattern;

public class Program1 {
	static final int MAX_INLEESGROOTTE_VERZAMELING = 10;

	PrintStream out;
	Scanner in;

	Verzameling verz1, verz2;

	public Program1() {
		out = new PrintStream(System.out);
		in = new Scanner(System.in);
		//in.useDelimiter("");
		verz1 = new Verzameling();
		verz2 = new Verzameling();
	}

	private void start() {
		while (leesVerzameling(verz1, in) 
				&& leesVerzameling(verz2, in)) {
			// Print Verschil
			out.print("Verschil: ");
			printVerzameling(verz1.verschil(verz2));
			// Print Doorsnede
			out.print("Doorsnede: ");
			printVerzameling(verz1.doorsnede(verz2));
			// Print Vereniging
			out.print("Vereniging: ");
			printVerzameling(verz1.vereniging(verz2));
			// Print Symmetrisch verschil
			out.print("Symmetrisch verschil: ");
			printVerzameling(verz1.symvers(verz2));
			out.print("\n");
		}
	}

	private boolean leesVerzameling (Verzameling dest, Scanner in) {
		while (true) {
			if (dest == verz1) {
				out.print("Geef eerste verzameling: ");
			} else {
				out.print("Geef tweede verzameling: ");
			}
			dest.init();
			// De invoer in een scanner stoppen.
			String input;
			try {
				input = in.nextLine();
			} catch (Exception e) {
				return false;
			}
			Scanner inputScanner = new Scanner(input);
			inputScanner.useDelimiter("");
			if(leesInvoer(inputScanner,dest)){
				return true;
			}
		}
	}

	private boolean leesInvoer(Scanner inputScanner,Verzameling dest){
		// Begin met inlezen, eerst checken of er wel wat is ingevoerd, vervolgens of het begint met een {.
		if(!scannerIsLeeg(inputScanner)) {
			if (nextCharIs(inputScanner, '{')) {
				inputScanner.next();
				if (leesIdentifiers(dest, inputScanner)) {
					return true;
				}
			} else {
				out.println("De '{' ontbreekt.");
			}
		}
		return false;

	}

	private boolean scannerIsLeeg(Scanner in) {
		while (in.hasNext()) {
			if(!nextCharIs(in, ' ')) {
				return false;
			}
			in.next();
		}
		return true;
	}

	private boolean leesIdentifiers(Verzameling dest, Scanner inputScanner) {
		while(inputScanner.hasNext()) {
			if(nextCharIsLetter(inputScanner)) {
				if(!voegElementToe(dest, inputScanner)) {
					return false;
				} 
			} else if (nextCharIs(inputScanner, ' ')) {
				inputScanner.next();
			} else if (nextCharIsDigit(inputScanner)){
				out.println("Een Identifier moet met een letter beginnen.");
				return false;
			} else if (nextCharIs(inputScanner, '}')){
				inputScanner.next();
				return checkOfRestInputLeeg(inputScanner);
			} else {
				out.println("De verzameling mag alleen letters A-Z en getallen 0-9 bevatten.");
				return false;
			}
		}
		out.println("De verzameling moet eindigen op een '}'");
		return false;
	}

	private boolean checkOfRestInputLeeg(Scanner inputScanner){
		if(scannerIsLeeg(inputScanner)) {
			return true;
		} else {
			out.println("Er mag niets na de verzameling staan.");
			return false;
		}
	}

	private Identifier leesIdentifier(Scanner in) {
		Identifier result = new Identifier();
		result.init(nextChar(in));
		while (nextCharIsLetter(in) || nextCharIsDigit(in)) {
			result.addChar(nextChar(in));
		}
		return result;
	}

	private boolean voegElementToe(Verzameling dest, Scanner inputScanner) {
		Identifier ident = leesIdentifier(inputScanner);
		if(dest.contains(ident)){
			return true;
		} else if (dest.size() < MAX_INLEESGROOTTE_VERZAMELING) {
			dest.add(ident);
			return true;
		} else {
			out.println("Je mag niet meer dan 10 Identifiers invoeren per verzameling.");
			return false;
		}
	}

	void printVerzameling(Verzameling verzameling) {
		Verzameling printVerzameling = new Verzameling(verzameling);
		int size = printVerzameling.size();
		for (int i = 0; i < size; i++) {
			Identifier ident = printVerzameling.take();
			out.printf(ident.read() + " ");
		}
		out.print("\n");
	}

	public static void main(String[] args) {
		new Program1().start();
	}

	char nextChar(Scanner in) {
		return in.next().charAt(0);
	}

	boolean nextCharIs(Scanner in, char c) {
		return in.hasNext(Pattern.quote(c+""));
	}

	boolean nextCharIsDigit (Scanner in) {
		return in.hasNext("[0-9]");
	}
	// Methode om te kijken of het volgende character dat gelezen
	// zou worden bij een aanroep van nextChar() een letter is.
	boolean nextCharIsLetter (Scanner in) {
		return in.hasNext("[a-zA-Z]");
	}
}
